import type { FC } from 'react';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import useSWR from 'swr';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { omit } from 'lodash-es';
import { ArrowRightIcon } from '@heroicons/react/24/solid';
import { RiErrorWarningFill } from '@remixicon/react';
import s from './index.module.css';
import cn from '@/utils/classnames';
import { FieldInfo } from '@/app/components/datasets/documents/detail/metadata';
import Button from '@/app/components/base/button';
import type { FullDocumentDetail, IndexingStatusResponse, ProcessRuleResponse } from '@/models/datasets';
import { fetchIndexingStatusBatch as doFetchIndexingStatus, fetchProcessRule } from '@/service/datasets';
import { DataSourceType } from '@/models/datasets';
import NotionIcon from '@/app/components/base/notion-icon';
import PriorityLabel from '@/app/components/billing/priority-label';
import { Plan } from '@/app/components/billing/type';
import { ZapFast } from '@/app/components/base/icons/src/vender/solid/general';
import UpgradeBtn from '@/app/components/billing/upgrade-btn';
import { useProviderContext } from '@/context/provider-context';
import Tooltip from '@/app/components/base/tooltip';
import { sleep } from '@/utils';

type Props = {
  datasetId: string;
  batchId: string;
  documents?: FullDocumentDetail[];
  indexingType?: string;
};

const RuleDetail: FC<{ sourceData?: ProcessRuleResponse }> = ({ sourceData }) => {
  const { t } = useTranslation();

  const segmentationRuleMap = {
    mode: t('datasetDocuments.embedding.mode'),
    segmentLength: t('datasetDocuments.embedding.segmentLength'),
    textCleaning: t('datasetDocuments.embedding.textCleaning'),
  };

  const getRuleName = (key: string) => {
    if (key === 'remove_extra_spaces') return t('datasetCreation.stepTwo.removeExtraSpaces');

    if (key === 'remove_urls_emails') return t('datasetCreation.stepTwo.removeUrlEmails');

    if (key === 'remove_stopwords') return t('datasetCreation.stepTwo.removeStopwords');
  };

  const getValue = useCallback(
    (field: string) => {
      let value: string | number | undefined = '-';
      switch (field) {
        case 'mode':
          value =
            sourceData?.mode === 'automatic'
              ? (t('datasetDocuments.embedding.automatic') as string)
              : (t('datasetDocuments.embedding.custom') as string);
          break;
        case 'segmentLength':
          value = sourceData?.rules?.segmentation?.max_tokens;
          break;
        default:
          value =
            sourceData?.mode === 'automatic'
              ? (t('datasetDocuments.embedding.automatic') as string)
              : // eslint-disable-next-line array-callback-return
                sourceData?.rules?.pre_processing_rules
                  ?.map((rule) => {
                    if (rule.enabled) return getRuleName(rule.id);
                  })
                  .filter(Boolean)
                  .join(';');
          break;
      }
      return value;
    },
    [sourceData],
  );

  return (
    <div className="flex flex-col pt-8 pb-10 first:mt-0">
      {Object.keys(segmentationRuleMap).map((field) => {
        return (
          <FieldInfo
            key={field}
            label={segmentationRuleMap[field as keyof typeof segmentationRuleMap]}
            displayedValue={String(getValue(field))}
          />
        );
      })}
    </div>
  );
};

const EmbeddingProcess: FC<Props> = ({ datasetId, batchId, documents = [], indexingType }) => {
  const { t } = useTranslation();
  const { enableBilling, plan } = useProviderContext();

  const getFirstDocument = documents[0];

  const [indexingStatusBatchDetail, setIndexingStatusDetail] = useState<IndexingStatusResponse[]>([]);
  const fetchIndexingStatus = async () => {
    const status = await doFetchIndexingStatus({ datasetId, batchId });
    setIndexingStatusDetail(status.data);
    return status.data;
  };

  const [isStopQuery, setIsStopQuery] = useState(false);
  const isStopQueryRef = useRef(isStopQuery);
  useEffect(() => {
    isStopQueryRef.current = isStopQuery;
  }, [isStopQuery]);
  const stopQueryStatus = () => {
    setIsStopQuery(true);
  };

  const startQueryStatus = async () => {
    if (isStopQueryRef.current) return;

    try {
      const indexingStatusBatchDetail = await fetchIndexingStatus();
      const isCompleted = indexingStatusBatchDetail.every((indexingStatusDetail) =>
        ['completed', 'error', 'paused'].includes(indexingStatusDetail.indexing_status),
      );
      if (isCompleted) {
        stopQueryStatus();
        return;
      }
      await sleep(2500);
      await startQueryStatus();
    } catch (e) {
      await sleep(2500);
      await startQueryStatus();
    }
  };

  useEffect(() => {
    startQueryStatus();
    return () => {
      stopQueryStatus();
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // get rule
  const { data: ruleDetail } = useSWR(
    {
      action: 'fetchProcessRule',
      params: { documentId: getFirstDocument.id },
    },
    (apiParams) => fetchProcessRule(omit(apiParams, 'action')),
    {
      revalidateOnFocus: false,
    },
  );

  const router = useNavigate();
  const navToDocumentList = () => {
    router(`/datasets/${datasetId}/documents`);
  };

  const isEmbedding = useMemo(() => {
    return indexingStatusBatchDetail.some((indexingStatusDetail) =>
      ['indexing', 'splitting', 'parsing', 'cleaning'].includes(indexingStatusDetail?.indexing_status || ''),
    );
  }, [indexingStatusBatchDetail]);
  const isEmbeddingCompleted = useMemo(() => {
    return indexingStatusBatchDetail.every((indexingStatusDetail) =>
      ['completed', 'error', 'paused'].includes(indexingStatusDetail?.indexing_status || ''),
    );
  }, [indexingStatusBatchDetail]);

  const getSourceName = (id: string) => {
    const doc = documents.find((document) => document.id === id);
    return doc?.name;
  };
  const getFileType = (name?: string) => name?.split('.').pop() || 'txt';
  const getSourcePercent = (detail: IndexingStatusResponse) => {
    const completedCount = detail.completed_segments || 0;
    const totalCount = detail.total_segments || 0;
    if (totalCount === 0) return 0;
    const percent = Math.round((completedCount * 100) / totalCount);
    return percent > 100 ? 100 : percent;
  };
  const getSourceType = (id: string) => {
    const doc = documents.find((document) => document.id === id);
    return doc?.data_source_type as DataSourceType;
  };

  const getIcon = (id: string) => {
    const doc = documents.find((document) => document.id === id);

    return doc?.data_source_info.notion_page_icon;
  };
  const isSourceEmbedding = (detail: IndexingStatusResponse) =>
    ['indexing', 'splitting', 'parsing', 'cleaning', 'waiting'].includes(detail.indexing_status || '');

  return (
    <>
      <div className="h-5 flex items-center mb-5">
        <div className={s.embeddingStatus}>
          {isEmbedding && t('datasetDocuments.embedding.processing')}
          {isEmbeddingCompleted && t('datasetDocuments.embedding.completed')}
        </div>
      </div>
      {enableBilling && plan.type !== Plan.team && (
        <div className="flex items-center mb-3 p-3 h-14 bg-white border-[0.5px] border-black/5 shadow-md rounded-xl">
          <div className="shrink-0 flex items-center justify-center w-8 h-8 bg-[#FFF6ED] rounded-lg">
            <ZapFast className="w-4 h-4 text-[#FB6514]" />
          </div>
          <div className="grow mx-3 text-[13px] font-medium text-gray-700">
            {t('billing.plansCommon.documentProcessingPriorityUpgrade')}
          </div>
          <UpgradeBtn loc="knowledge-speed-up" />
        </div>
      )}
      <div className={s.progressContainer}>
        {indexingStatusBatchDetail.map((indexingStatusDetail) => (
          <div
            key={indexingStatusDetail.id}
            className={cn(
              s.sourceItem,
              indexingStatusDetail.indexing_status === 'error' && s.error,
              indexingStatusDetail.indexing_status === 'completed' && s.success,
            )}
          >
            {isSourceEmbedding(indexingStatusDetail) && (
              <div className={s.progressbar} style={{ width: `${getSourcePercent(indexingStatusDetail)}%` }} />
            )}
            <div className={`${s.info} grow`}>
              {getSourceType(indexingStatusDetail.id) === DataSourceType.FILE && (
                <div className={cn(s.fileIcon, s[getFileType(getSourceName(indexingStatusDetail.id))])} />
              )}
              {getSourceType(indexingStatusDetail.id) === DataSourceType.NOTION && (
                <NotionIcon className="shrink-0 mr-1" type="page" src={getIcon(indexingStatusDetail.id)} />
              )}
              <div className={`${s.name} truncate`} title={getSourceName(indexingStatusDetail.id)}>
                {getSourceName(indexingStatusDetail.id)}
              </div>
              {enableBilling && <PriorityLabel />}
            </div>
            <div className="shrink-0">
              {isSourceEmbedding(indexingStatusDetail) && <div className={s.percent}>{`${getSourcePercent(indexingStatusDetail)}%`}</div>}
              {indexingStatusDetail.indexing_status === 'error' && indexingStatusDetail.error && (
                <Tooltip popupContent={<div className="max-w-[400px]">{indexingStatusDetail.error}</div>}>
                  <div className={cn(s.percent, s.error, 'flex items-center')}>
                    Error
                    <RiErrorWarningFill className="ml-1 w-4 h-4" />
                  </div>
                </Tooltip>
              )}
              {indexingStatusDetail.indexing_status === 'error' && !indexingStatusDetail.error && (
                <div className={cn(s.percent, s.error, 'flex items-center')}>Error</div>
              )}
              {indexingStatusDetail.indexing_status === 'completed' && <div className={cn(s.percent, s.success)}>100%</div>}
            </div>
          </div>
        ))}
      </div>
      <RuleDetail sourceData={ruleDetail} />
      <div className="flex items-center gap-2 mt-10">
        <Button className="w-fit" variant="primary" onClick={navToDocumentList}>
          <span>{t('datasetCreation.stepThree.navTo')}</span>
          <ArrowRightIcon className="h-4 w-4 ml-2 stroke-current stroke-1" />
        </Button>
      </div>
    </>
  );
};

export default EmbeddingProcess;
